#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
THN DATA ABSTRACTION LAYER version 1

Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

This library is dual-licensed.
  + For commercial software, please obtain a commercial license from THN Solutions LLC.

  + For free software, this library is licensed under GPL version 3. A summary of GPLv3 is
    listed below. You should also find a copy of GPLv3 as file License_GPLv3.txt included
	with the source-code files.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 3 as published by
    the Free Software Foundation  of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

#region Using directives
using System;
using System.Data;
using System.Data.OleDb;
using Thn.Data.Database.Sql.Dialect;
using System.Collections;
using Thn.Data.Mapping;
using Thn.Data.Exceptions;
using Thn.Data.Settings;
using System.Text;
using Thn.Application;
#endregion

namespace Thn.Data.Database.Sql
{
    /// <summary>
    /// Adapter for Microsoft Access database
    /// </summary>
    public class AccessDatabase: AbstractSqlDatabase
    {
        #region On Insert Object
        /// <summary>
        /// Raised after insert command has been built, this method will execute the command.
        /// <para>Override this method for acquiring auto-generated IDs, etc.</para>
        /// </summary>
        /// <param name="value">the data object to be inserted</param>
        /// <param name="command">the prepared database command</param>
        /// <param name="entity">mapping of object to insert</param>
        /// <param name="attributes">mapping of attributes</param>
        /// <param name="hasAuto">Whether identifier of object is auto-generated field</param>
        protected override void OnInsertObject(object value, IDbCommand command, ObjectMap entity, AttributeMap[] attributes, bool hasAuto)
        {
            if (hasAuto)
            {//override to retrieve ID of the object inserted and put it back to the object

                //find the first identifier
                AttributeMap id = null;
                for (int i = 0; i < attributes.Length; i++)
                {
                    if (attributes[i].IsIdentifier)
                    {
                        id = attributes[i];
                        break;
                    }
                }

                //throw exception if could not find any identifier
                if (id == null) NoIdentifierException.Publish(entity.ObjectEntity);

                //execute insert query
                ExecuteNonQuery(command, false);

                //Select the max value to guess the new id
                IDbCommand cmd = Dialect.CreateCommand();
                cmd.CommandText += "SELECT MAX(" + id.DataAttribute + ") FROM " + entity.DataEntity;

                //execute query
                object idValue = ExecuteScalar(cmd, true);

                //put the new id back to the object
                if (idValue != null)
                {
                    Mapper.SetObjectAttributeValue(value, id, idValue);
                }
            }
            else base.OnInsertObject(value, command, entity, attributes, hasAuto);
        }
        #endregion

        #region I/O
        #region Refresh
        /// <summary>
        /// Refresh/load data, if neccessary
        /// </summary>
        public override void Refresh() { }
        #endregion

        #region Flush
        /// <summary>
        /// Persist changes to database, if still buffered
        /// </summary>
        public override void Flush() { }
        #endregion
        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        public AccessDatabase()
        {
            this.Dialect = new AccessDialect();
        }
        #endregion
    }
}

